home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the 3D Game Programming Gurus / gurus.iso / DirectX / dx9sdkcp.exe / SDK (C++) / Bin / DXUtils / Visual Studio 6.0 Wizards / Source Code / Template / diutil.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2002-11-12  |  11.2 KB  |  362 lines

  1. //-----------------------------------------------------------------------------
  2. // File: DIUtil.cpp
  3. //
  4. // Desc: DirectInput framework class using semantic mapping.  Feel free to use 
  5. //       this class as a starting point for adding extra functionality.
  6. //-----------------------------------------------------------------------------
  7. #define STRICT
  8. $$IF(DLG)
  9. #include "stdafx.h"
  10. $$ENDIF
  11. #include <basetsd.h>
  12. #include <tchar.h>
  13. #include <stdio.h>
  14. #include "DIUtil.h"
  15. #include "DXUtil.h"
  16.  
  17.  
  18.  
  19.  
  20.  
  21. //-----------------------------------------------------------------------------
  22. // Name: CInputDeviceManager()
  23. // Desc: Constructor 
  24. //-----------------------------------------------------------------------------
  25. CInputDeviceManager::CInputDeviceManager()
  26. {
  27.     HRESULT hr = CoInitialize(NULL);
  28.     m_bCleanupCOM = SUCCEEDED(hr);
  29.  
  30.     m_dwNumDevices = 0;
  31.     m_dwMaxDevices = 10;
  32.     m_pDI          = NULL;
  33.  
  34.     // Allocate DeviceInfo structs
  35.     m_pDevices = (DeviceInfo*) malloc( m_dwMaxDevices*sizeof(DeviceInfo) );
  36.     if( m_pDevices )
  37.         ZeroMemory( m_pDevices, m_dwMaxDevices*sizeof(DeviceInfo) );
  38. }
  39.  
  40.  
  41.  
  42.  
  43. //-----------------------------------------------------------------------------
  44. // Name: ~CInputDeviceManager()
  45. // Desc: Destructor
  46. //-----------------------------------------------------------------------------
  47. CInputDeviceManager::~CInputDeviceManager()
  48. {
  49.     if( m_pDevices )
  50.     {
  51.         // Release() all devices
  52.         for( DWORD i=0; i<m_dwNumDevices; i++ )
  53.         {
  54.             if( m_pDevices[i].pdidDevice )
  55.                 m_pDevices[i].pdidDevice->Unacquire();
  56.  
  57.             SAFE_RELEASE( m_pDevices[i].pdidDevice );
  58.         }
  59.  
  60.         free( m_pDevices );
  61.     }
  62.  
  63.     // Release() base object
  64.     SAFE_RELEASE( m_pDI );
  65.  
  66.     if( m_bCleanupCOM )
  67.         CoUninitialize();
  68. }
  69.  
  70.  
  71.  
  72.  
  73. //-----------------------------------------------------------------------------
  74. // Name: GetDevices()
  75. // Desc: Get the DeviceInfo array and number of devices
  76. //-----------------------------------------------------------------------------
  77. HRESULT CInputDeviceManager::GetDevices( DeviceInfo** ppDeviceInfo, 
  78.                                          DWORD* pdwCount )
  79. {
  80.     if( NULL==ppDeviceInfo || NULL==pdwCount )
  81.         return E_INVALIDARG;
  82.  
  83.     (*ppDeviceInfo) = m_pDevices;
  84.     (*pdwCount) = m_dwNumDevices;
  85.  
  86.     return S_OK;
  87. }
  88.  
  89.  
  90.  
  91.  
  92. //-----------------------------------------------------------------------------
  93. // Name: AddDevice()
  94. // Desc: Add the provided device to the list and perform initialization
  95. //-----------------------------------------------------------------------------
  96. HRESULT CInputDeviceManager::AddDevice( const DIDEVICEINSTANCE* pdidi, 
  97.                                         const LPDIRECTINPUTDEVICE8 pdidDevice )
  98. {
  99.     HRESULT hr;
  100.  
  101.     // Sanity check
  102.     if( NULL == pdidDevice )
  103.         return E_INVALIDARG;
  104.  
  105.     pdidDevice->Unacquire();
  106.  
  107.     // Set the device's coop level
  108.     hr = pdidDevice->SetCooperativeLevel( m_hWnd, DISCL_NONEXCLUSIVE|DISCL_FOREGROUND );
  109.     if( FAILED(hr) )
  110.         return hr;
  111.  
  112.     // Enlarge the array if needed
  113.     if( m_dwNumDevices >= m_dwMaxDevices )
  114.     {
  115.         // Attempt to reallocate memory
  116.         DWORD dwNewMax = m_dwMaxDevices + 10;
  117.         DeviceInfo* pNewDevices = (DeviceInfo*) realloc( m_pDevices, sizeof(DeviceInfo) * dwNewMax );
  118.         
  119.         // Check for out of memory condition
  120.         if( NULL == pNewDevices )
  121.             return E_OUTOFMEMORY;
  122.  
  123.         // Initialize the new memory block
  124.         ZeroMemory( pNewDevices + m_dwMaxDevices, sizeof(DeviceInfo) * (dwNewMax - m_dwMaxDevices) );
  125.  
  126.         // Copy the new pointer and update the max device count
  127.         m_pDevices = pNewDevices;
  128.         m_dwMaxDevices = dwNewMax;
  129.     }
  130.  
  131.     // Add new device to the end of the list, but don't finalize addition until
  132.     // the end of the function. If the remaining initialization calls fail, this
  133.     // spot will be used by the next valid device.
  134.     m_pDevices[m_dwNumDevices].pdidDevice = pdidDevice;
  135.     
  136.     // Callback into the app so it can adjust the device and set
  137.     // the m_pDevices[dwCurrentDevice].pParam field with a device state struct
  138.     if( m_AddDeviceCallback )
  139.     {
  140.         hr = m_AddDeviceCallback( &m_pDevices[m_dwNumDevices], pdidi, m_AddDeviceCallbackParam ); 
  141.         if( FAILED(hr) )    
  142.             return hr;
  143.     }
  144.  
  145.     // Build the action map
  146.     hr = m_pDevices[m_dwNumDevices].pdidDevice->BuildActionMap( &m_diaf, m_strUserName, 0 );
  147.     if( FAILED(hr) )
  148.         return hr;
  149.  
  150.     // Set the action map for the current device
  151.     hr = m_pDevices[m_dwNumDevices].pdidDevice->SetActionMap( &m_diaf, m_strUserName, 0 );
  152.     if( FAILED(hr) )
  153.         return hr;
  154.  
  155.     // Device addition succeeded. Increment reference and index.
  156.     m_pDevices[m_dwNumDevices].pdidDevice->AddRef();
  157.     m_dwNumDevices++;
  158.  
  159.     // Continue enumerating suitable devices
  160.     return S_OK;
  161. }
  162.  
  163.  
  164.  
  165.  
  166. //-----------------------------------------------------------------------------
  167. // Name: EnumSuitableDevicesCB()
  168. // Desc: Callback function for device enumeration. Adds all devices which
  169. //       met the search criteria
  170. //-----------------------------------------------------------------------------
  171. BOOL CALLBACK EnumSuitableDevicesCB( LPCDIDEVICEINSTANCE pdidi, 
  172.                                      LPDIRECTINPUTDEVICE8 pdidDevice, 
  173.                                      DWORD dwFlags, DWORD dwDeviceRemaining,
  174.                                      VOID* pContext )
  175. {
  176.     UNREFERENCED_PARAMETER( dwFlags );
  177.     UNREFERENCED_PARAMETER( dwDeviceRemaining );
  178.     
  179.     // Add the device to the device manager's internal list
  180.     ((CInputDeviceManager*)pContext)->AddDevice( pdidi, pdidDevice );
  181.  
  182.     // Continue enumerating suitable devices
  183.     return DIENUM_CONTINUE;
  184. }
  185.  
  186.  
  187.  
  188.  
  189. //-----------------------------------------------------------------------------
  190. // Name: SetActionFormat()
  191. // Desc: Set the action format to the provided DIACTIONFORMAT structure, and
  192. //       destroy and recreate device list if flagged
  193. //-----------------------------------------------------------------------------
  194. HRESULT CInputDeviceManager::SetActionFormat( DIACTIONFORMAT& diaf, BOOL bReenumerate )
  195. {
  196.     HRESULT hr = S_OK;
  197.  
  198.     // Store the new action format
  199.     m_diaf = diaf;
  200.  
  201.     // Only destroy and re-enumerate devices if the caller explicitly wants to. The 
  202.     // device list may be used within a loop, and kicking off an enumeration while 
  203.     // the device array is in use would cause problems.
  204.     if( bReenumerate )
  205.     {
  206.         // Cleanup any previously enumerated devices
  207.         for( DWORD i=0; i<m_dwNumDevices; i++ )
  208.         {
  209.             if( m_pDevices[i].pdidDevice )
  210.                 m_pDevices[i].pdidDevice->Unacquire();
  211.  
  212.             SAFE_RELEASE( m_pDevices[i].pdidDevice );
  213.         }
  214.         m_dwNumDevices = 0;
  215.  
  216.         // Enumerate suitable DirectInput devices
  217.         hr = m_pDI->EnumDevicesBySemantics( m_strUserName, &m_diaf, 
  218.                                             EnumSuitableDevicesCB, this, 0L );
  219.         if( FAILED(hr) )
  220.             return hr;
  221.     }
  222.     else // Just apply the new maps.
  223.     {
  224.         // Devices must be unacquired to have a new action map set.
  225.         UnacquireDevices();
  226.  
  227.         // Apply the new action map to the current devices.
  228.         for( DWORD i=0; i<m_dwNumDevices; i++ )
  229.         {
  230.             hr = m_pDevices[i].pdidDevice->BuildActionMap( &m_diaf, m_strUserName, 0 );
  231.             if( FAILED(hr) )
  232.                 return hr;
  233.  
  234.             hr = m_pDevices[i].pdidDevice->SetActionMap( &m_diaf, m_strUserName, 0 );
  235.             if( FAILED(hr) )
  236.                 return hr;
  237.         }
  238.     }
  239.  
  240.     return S_OK;
  241. }
  242.  
  243.  
  244.  
  245.  
  246. //-----------------------------------------------------------------------------
  247. // Name: Create()
  248. // Desc: Create DirectInput object and perform initialization
  249. //-----------------------------------------------------------------------------
  250. HRESULT CInputDeviceManager::Create( HWND hWnd, TCHAR* strUserName, 
  251.                                      DIACTIONFORMAT& diaf,
  252.                                      LPDIMANAGERCALLBACK AddDeviceCallback, 
  253.                                      LPVOID pCallbackParam )
  254. {
  255.     HRESULT hr;
  256.  
  257.     // Store data
  258.     m_hWnd        = hWnd;
  259.     m_strUserName = strUserName;
  260.     m_AddDeviceCallback = AddDeviceCallback;
  261.     m_AddDeviceCallbackParam = pCallbackParam;
  262.     
  263.     // Create the base DirectInput object
  264.     hr = DirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION, 
  265.                               IID_IDirectInput8, (VOID**)&m_pDI, NULL );
  266.     if( FAILED(hr) )
  267.         return hr;
  268.  
  269.     hr = SetActionFormat( diaf, TRUE );
  270.     if( FAILED(hr) )
  271.         return hr;
  272.  
  273.     return S_OK;
  274. }
  275.  
  276.  
  277.  
  278.  
  279. //-----------------------------------------------------------------------------
  280. // Name: ConfigureDevices()
  281. // Desc: Pause input and display the device configuration UI
  282. //-----------------------------------------------------------------------------
  283. HRESULT CInputDeviceManager::ConfigureDevices( HWND hWnd, IUnknown* pSurface,
  284.                                                VOID* ConfigureDevicesCB,
  285.                                                DWORD dwFlags, LPVOID pvCBParam )
  286. {
  287.     HRESULT hr;
  288.  
  289.     // Initialize all the colors here
  290.     DICOLORSET dics;
  291.     ZeroMemory(&dics, sizeof(DICOLORSET));
  292.     dics.dwSize = sizeof(DICOLORSET);
  293.  
  294.     // Fill in all the params
  295.     DICONFIGUREDEVICESPARAMS dicdp;
  296.     ZeroMemory(&dicdp, sizeof(dicdp));
  297.     dicdp.dwSize = sizeof(dicdp);
  298.     dicdp.dwcFormats     = 1;
  299.     dicdp.lprgFormats    = &m_diaf;
  300.     dicdp.hwnd           = hWnd;
  301.     dicdp.lpUnkDDSTarget = pSurface;
  302.  
  303.     if( m_strUserName )
  304.     {
  305.         dicdp.dwcUsers       = 1;
  306.         dicdp.lptszUserNames = m_strUserName;
  307.     }
  308.  
  309.     // Unacquire the devices so that mouse doesn't control the game while in control panel
  310.     UnacquireDevices();
  311.  
  312.     hr = m_pDI->ConfigureDevices( (LPDICONFIGUREDEVICESCALLBACK)ConfigureDevicesCB, 
  313.                                   &dicdp, dwFlags, pvCBParam );
  314.     if( FAILED(hr) )
  315.         return hr;
  316.  
  317.     if( dwFlags & DICD_EDIT )
  318.     {
  319.         // Re-set up the devices
  320.         hr = SetActionFormat( m_diaf, TRUE );
  321.         if( FAILED(hr) )
  322.             return hr;
  323.     }
  324.  
  325.     return S_OK;
  326. }
  327.  
  328.  
  329.  
  330. //-----------------------------------------------------------------------------
  331. // Name: UnacquireDevices()
  332. // Desc: Unacquire all devices in the member list
  333. //-----------------------------------------------------------------------------
  334. VOID CInputDeviceManager::UnacquireDevices()
  335. {
  336.     for( DWORD i=0; i<m_dwNumDevices; i++ )
  337.         m_pDevices[i].pdidDevice->Unacquire();
  338. }
  339.  
  340.  
  341.  
  342.  
  343. //-----------------------------------------------------------------------------
  344. // Name: SetFocus()
  345. // Desc: Sets the DirectInput focus to a new HWND
  346. //-----------------------------------------------------------------------------
  347. VOID CInputDeviceManager::SetFocus( HWND hWnd ) 
  348. {
  349.     m_hWnd = hWnd;
  350.  
  351.     UnacquireDevices();
  352.  
  353.     for( DWORD i=0; i<m_dwNumDevices; i++ )
  354.     {
  355.         // Set the device's coop level
  356.         m_pDevices[i].pdidDevice->SetCooperativeLevel( m_hWnd, 
  357.                                         DISCL_NONEXCLUSIVE|DISCL_FOREGROUND );
  358.     }
  359. }
  360.  
  361.  
  362.